package priv.dajie.tzzq.core;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import priv.dajie.tzzq.bot.BotManager;
import priv.dajie.tzzq.bot.buff.BuffBot;
import priv.dajie.tzzq.bot.c5.C5Bot;
import priv.dajie.tzzq.bot.exception.BuyException;
import priv.dajie.tzzq.bot.exception.NetworkException;
import priv.dajie.tzzq.bot.model.BuyResult;
import priv.dajie.tzzq.bot.model.BuyState;
import priv.dajie.tzzq.bot.model.HistoryPrices;
import priv.dajie.tzzq.bot.model.SellItem;
import priv.dajie.tzzq.bot.steam.SteamBot;
import priv.dajie.tzzq.bot.steam.exception.SteamGetMinPriceException;
import priv.dajie.tzzq.common.ApplicationContextUnit;
import priv.dajie.tzzq.service.ScanCacheService;
import priv.dajie.tzzq.service.TradeService;
import priv.dajie.tzzq.spider.SpiderManager;
import priv.dajie.tzzq.spider.model.Platform;
import priv.dajie.tzzq.model.*;
import priv.dajie.tzzq.common.Retryer;
import priv.dajie.tzzq.common.SteamPrice;
import priv.dajie.tzzq.common.Tools;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

public class AutoBuy implements Runnable {

    private SpiderManager spiderManager = SpiderManager.getInstance();
    private C5Bot c5Bot;
    private BuffBot buffBot;
    private SteamBot steamBot;
    private Logger logger = LogManager.getLogger(this.getClass());
    private long lastTime;
    private BigDecimal rate;

    private TradeService tradeService = ApplicationContextUnit.getInstance().getBean(TradeService.class);
    private ScanCacheService scanCacheService = ApplicationContextUnit.getInstance().getBean(ScanCacheService.class);


    public AutoBuy(double rate) {
        lastTime = Tools.loadLastRunTime();
        c5Bot = BotManager.getC5Bot();
        buffBot = BotManager.getBuffBot();
        steamBot = BotManager.getSteamBot();
        this.rate = new BigDecimal(rate);
    }

    public void startSteamSpider() {
        if ((System.currentTimeMillis() - lastTime) > 60 * 60 * 2 * 1000) {
            logger.info("启动Steam爬虫");
            spiderManager.startSteamSpider();
            Tools.saveLastRunTime(System.currentTimeMillis());
            lastTime = System.currentTimeMillis();
        }
    }

    public void startBuy() {
        List<BuyCompareItem> buyCompareItems = tradeService.listBuyItem();
        int n = 0;
        BigDecimal sellPriceSum = new BigDecimal("0");
        BigDecimal buyPriceSum = new BigDecimal("0");
        for (BuyCompareItem buyCompareItem : buyCompareItems) {
            AnalysisItem analysisItem;
            try {
                analysisItem = analysis(buyCompareItem);
            }catch (Exception e){
                continue;
            }

            if (analysisItem.getCode() == Code.SUCCESS) {
                n = 0;
                try {
                    if (analysisItem.getSellItem().getPrice().compareTo(new BigDecimal("15")) > 0) {
                        System.out.print("是否购买->");
                        continue;
//                        Scanner scanner = new Scanner(System.in);
//                        if (!scanner.nextLine().equals("Y"))
//                        continue;
                    }
                    // 进行购买
                    BuyResult buyResult;
                    while (true) {
                        try {
                            buyResult = buy(analysisItem);
                            break;
                        }catch (NetworkException e){
                            logger.error(e);
                        }
                    }
                    if (buyResult.getBuyState() == BuyState.SUCCESS || buyResult.getBuyState() == BuyState.WAIT || buyResult.getBuyState() == BuyState.TAKE_BACK) {
                        logger.info("购买状态:" + buyResult);
                        tradeService.addTrade(new BuyGoods(buyCompareItem.getSteamName(), analysisItem.getSellItem().getPrice(), analysisItem.getPlatform(), buyResult.getBuyID(), buyResult.getBuyState() ,analysisItem.getSteamPrice()));
                        sellPriceSum = sellPriceSum.add(analysisItem.getSteamPrice());
                        buyPriceSum = buyPriceSum.add(analysisItem.getSellItem().getPrice());
                    } else {
                        logger.warn("购买状态:" + buyResult);
                    }
//
                } catch (BuyException e) {
                    e.printStackTrace();
                }
            } else if (analysisItem.getCode() == Code.LOW_RATE) {
                if (n > 50) {
                    break;
                }
                n++;
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        logger.info("购买金额：" + buyPriceSum + " | 预计收益：" + sellPriceSum );
        logger.info(" 收益比：" + sellPriceSum.divide(buyPriceSum, 2 ,BigDecimal.ROUND_CEILING));
    }

    private BuyResult buy(AnalysisItem analysisItem) throws BuyException {
        BuyResult buyResult;
        if (analysisItem.getPlatform() == Platform.C5) {
            buyResult = c5Bot.buyPro(analysisItem.getSellItem(), analysisItem.getGoodsID());
        } else {
            buyResult = buffBot.buyPro(analysisItem.getSellItem(), analysisItem.getGoodsID());
        }
        return buyResult;

    }

    private void receive(BuyResult buyResult){

        String tradeId = c5Bot.autoReceiveOffer(buyResult.getTakeBackId());
        String successId = steamBot.trade(tradeId);
        steamBot.getTradeItems(successId);

        //        for (String steamName : takeBackSteamName) {
//            logger.info(steamName + "：取回成功");
//            TradeTable.getInstance().updateState(tradeStateItemHashMap.get(steamName).getId(), GoodsState.PACKAGE, 0); // 取回成功的商品设置为待上架
//        }

    }

    private AnalysisItem analysis(BuyCompareItem buyCompareItem) { // 分析是否值得购买
        BigDecimal steamPrice;
        try {
            steamPrice = steamBot.getMinPrice(buyCompareItem.getNameId());
        } catch (SteamGetMinPriceException e) {
            logger.error(e);
            return new AnalysisItem(Code.ERROR);
        }
        BigDecimal steamFeePrice = SteamPrice.feePrice(steamPrice);
        List<SellItem> c5SellItems;
        List<SellItem> buffSellItems;
        int error = 1;
        while (true) {
            try {
                c5SellItems = c5Bot.getSellItemsByID(buyCompareItem.getC5Id());
                buffSellItems = buffBot.getSellItemsByID(buyCompareItem.getBuffId());
                break;
            } catch (Exception e) {
                logger.error("获取c5、buff商品失败：正在重试第" + error + "次："+e);
                if (error > 5) {
                    return new AnalysisItem(Code.ERROR);
                }
                try {
                    Thread.sleep(1000 * error++);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }

        Platform platform;
        SellItem minItem;
        String goodsID;
        if (c5SellItems.size() > 0 && buffSellItems.size() > 0) {
            if (c5SellItems.get(0).getPrice().compareTo(buffSellItems.get(0).getPrice())<=0) {
                platform = Platform.C5;
                minItem = c5SellItems.get(0);
                goodsID = buyCompareItem.getC5Id();
            } else {
                platform = Platform.BUFF;
                minItem = buffSellItems.get(0);
                goodsID = buyCompareItem.getBuffId();
            }
        } else if (c5SellItems.size() > 0) {
            platform = Platform.C5;
            minItem = c5SellItems.get(0);
            goodsID = buyCompareItem.getC5Id();
        } else if (buffSellItems.size() > 0) {
            platform = Platform.BUFF;
            minItem = buffSellItems.get(0);
            goodsID = buyCompareItem.getBuffId();
        } else {
            logger.info(buyCompareItem.getQualityName() + "：平台无货");
            scanCacheService.addScanCacheItem(new ScanCacheItem(buyCompareItem.getSteamName(), new Date(System.currentTimeMillis() + 60 * 60 * 18 * (long) 1000)));
            return new AnalysisItem(Code.GOODLESS);
        }
        // 净利润 收益比 (销售价-购买价)/购买价
        BigDecimal realRate = steamFeePrice.divide(minItem.getPrice(), 3, BigDecimal.ROUND_CEILING).subtract(new BigDecimal("1"));
        BigDecimal sellRate = steamFeePrice.subtract(new BigDecimal("0.01")).divide(minItem.getPrice(),3, BigDecimal.ROUND_CEILING).subtract(new BigDecimal("1"));
        if (realRate.compareTo(rate)<0 || sellRate.compareTo(new BigDecimal("1.45"))<0) {
            logger.info(buyCompareItem.getQualityName() + " -> 不符合要求 当前收益比：" + realRate + " 出售收益比："+ sellRate);
            return new AnalysisItem(Code.LOW_RATE);
        }
        final HistoryPrices[] historyPrices = new HistoryPrices[1];
        Retryer.retry(() -> historyPrices[0] = steamBot.getHistoryPrices(buyCompareItem.getSteamName()));
        double effectiveAvg = historyPrices[0].effective(7) ;
        double deviationRate = historyPrices[0].deviationRate(7);
        if (effectiveAvg < 7
        ) {
            logger.info(buyCompareItem.getQualityName() + "-> 日均销量过低:" + effectiveAvg);
            scanCacheService.addScanCacheItem(new ScanCacheItem(buyCompareItem.getSteamName(), new Date(System.currentTimeMillis() + 60 * 60 * 24 * (long) 1000)));
            return new AnalysisItem(Code.LOW_SALES);
        }
        // 判断偏差率<=1 判断销售量
        if (deviationRate > 1) {
            logger.info(buyCompareItem.getQualityName() + "-> 偏差比过高:" + deviationRate);
            scanCacheService.addScanCacheItem(new ScanCacheItem(buyCompareItem.getSteamName(), new Date(System.currentTimeMillis() + 60 * 60 * 20 * (long) 1000)));
            return new AnalysisItem(Code.HIGH_VOL);
        }
        logger.info(buyCompareItem.getQualityName() + "-> 符合要求 购买价:" + minItem.getPrice() + " 出售价:" + steamFeePrice + " 差价比:" + realRate);
        return new AnalysisItem(Code.SUCCESS, minItem, platform, goodsID, steamFeePrice);
    }

    @Override
    public void run() {
        while (true) {
            try {
                startSteamSpider();
                SpiderManager.getInstance().startBuffSpider();
                SpiderManager.getInstance().startC5Spider();
                startBuy();
                logger.info("执行完毕");
                Thread.sleep(60 * 5 * 1000);
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    Thread.sleep(60 * 1000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        AutoBuy autoBuy = new AutoBuy(1.5);
        Thread t = new Thread(autoBuy);
        t.start();
    }
}

